#pragma once

#ifndef _NET_MANAGER_H_
#define _NET_MANAGER_H_

#include <vector>
#include <memory>
#include <queue>
#include <map>
#include "as_address.h"
#include "as_callback.h"
#include "mailpos.h"
#include "remotemail.h"
#include "timer_mgr.h"

namespace as
{

namespace net
{
class EpollWatch;
class TcpClient;
typedef std::shared_ptr<TcpClient> TcpClientPtr;
}

namespace md
{
class Actor;
class ActorClient;
typedef std::shared_ptr<ActorClient> ActorClientPtr;
class ActorServer;

class NetManager 
{
public:
	using OnActorMessageByName = std::function<void(MailPos&, std::string&, ByteBufferPtr)>;
	using OnActorMessageByAddress = std::function<void(MailPos&, MailPos&, ByteBufferPtr)>;
	NetManager(as::net::EpollWatch *ep, as::net::Address &addr, const char *name, int pri_key);
	~NetManager();

	void Start();
	void Stop();

	void RegisterTcpClient(int id, as::net::TcpClient *client);
	void SendMsg(ByteBufferPtr &buf, const MailPos &sender, const MailPos &recipient);
	void SendMsg(ByteBufferPtr &buf, const MailPos &sender, const char *recipientName, int pri_key);
	void SendAll(ByteBufferPtr &buf, const MailPos &sender);

	void HandleActorMsg(ByteBufferPtr &buf, int readn);
	void HandleConnChange(int remoteId, as::net::TcpClient *conn);


	void PushSendMsg(RemoteMailPtr &mail);
	void ProcessMsg();
	void Run();

	void AddRemoteAddr(as::net::Address &addr);
	void RegisterRemoteMsg(OnActorMessageByAddress f1, OnActorMessageByName f2);
private:
	const int pri_key_;
	as::net::EpollWatch *ep_;
	std::vector<ActorClient*> clients_;
	std::map<int, ActorClient*> clients_map_;
	std::shared_ptr<ActorServer> server_;
	std::queue<RemoteMailPtr> send_cache_;
	TimerMgr timer_;
	bool remote_all_finish_ = false;
	OnActorMessageByAddress msg_addr_cb_;
	OnActorMessageByName msg_name_cb_;
};















	}
}

#endif